/**************************************************************************//**
 * @item     CosyOS Config
 * @file     mcucfg_cmx.c
 * @brief    CMSIS Cortex-M Core Config File
 * @author   迟凯峰
 * @version  V2.3.0
 * @date     2023.04.25
 ******************************************************************************/

#include "..\System\glovar.h"
#ifdef __MCUCFG_CMX_H

#include "..\System\sysapi.h"
#include "..\System\svs.h"
u32 vBASEPRI = 1;
volatile u8 vPOPUSH = 0;
tspTaskNode vNEWTASK;
void *vISS[MCUCFG_ISSDEPTH];
register void **vISP __ASM("r11");
#if SYSCFG_DIRMSG == __ENABLED__
u32 * volatile vDM_PSP;
#endif
#if MCUCFG_SVSTACKMONITOR == __ENABLED__
volatile u32 vISS_DepthMAX = 0;
#endif

__ASM u32 __get_HLP(void)
{
	extern __heap_limit;
	ldr r0, =__heap_limit
	bx lr
}

__ASM void __isp_push(void *p)
{
	str r0, [r11,#4]!
	bx lr
}

static __ASM void *__isp_pop(void)
{
	ldr r0, [r11], #-4
	bx lr
}

void __isv(void)
{
	while(vISP > vISS)
	{
		register void *svs __ASM("r0");
		#if MCUCFG_SVSTACKMONITOR == __ENABLED__
		register u32 depth = (u32)(vISP - vISS) + 1;
		if(depth > vISS_DepthMAX)
		{
			vISS_DepthMAX = depth;
		}
		#endif
		svs = __isp_pop();
		sISS_Handler
	}
}

__ASM void PendSV_Handler(void)
{
__ext
	extern vPOPUSH;
	extern vNEWTASK;
	extern vTASKING;
	extern vISS;
	extern vPC;
	extern vScheduling_f;
	extern vTaskmgrBinary;
	extern __isv;
	extern Task_Scheduler;
	
	push {lr}
	
__ISV
	ldr r0, =vISS
	sub r0, r11, r0
	cbz r0, __SCH
	bl __isv
	
__SCH
	ldr r1, =vScheduling_f
	ldrb r0, [r1]
	cbz r0, __RET
	mov r2, #0
	strb r2, [r1]
	bl Task_Scheduler
	
__INIT
	ldr r1, =vPOPUSH
	ldrb r0, [r1]
	mov r2, #0
	strb r2, [r1]
	cbz r0, __RET
	PRESERVE8
	ldr r3, =vTASKING
	sub r0, r0, #1
	cbz r0, __POP
	mrs r0, psp
	isb
	
__PC
	IF SYSCFG_TASKPCMONITOR == __ENABLED__
	ldr r1, =vTaskmgrBinary
	ldrb r2, [r1]
	cbz r2, __PUSH
	mov r1, r0
	add r1, #24
	ldmia r1, {r2}
	ldr r1, =vPC
	str r2, [r1]
	nop
	ENDIF
	
__PUSH
	IF MCUCFG_HARDWAREFPU == __ENABLED__
	vstmdb r0!, {s16-s31}
	ENDIF
	stmdb r0!, {r4-r10}
	ldr r1, [r3]
	str r0, [r1]
	
__POP
	ldr r2, =vNEWTASK
	ldr r1, [r2]
	str r1, [r3]
	ldr r0, [r1]
	ldmia r0!, {r4-r10}
	IF MCUCFG_HARDWAREFPU == __ENABLED__
	vldmia r0!, {s16-s31}
	ENDIF
	msr psp, r0
	
__RET
	pop {pc}
}

#if MCUCFG_TASKSTACKMONITOR == __ENABLED__

void __entry_monitor(void)
{
	register tStackSize stacklen = vTASKING->PSBP - __get_PSP() + __BASICSTACKSIZE__;
	if(stacklen > vTASKING->stacklen_max)
	{
		vTASKING->stacklen_max = stacklen;
	}
	if(stacklen > vTASKING->stacksize)
	{
		vTASKING->state = __STOPPED_TSOF__;
		vScheduling_f = true;
		mPSV_Trigger;
		while(true);
	}
}

#endif

#endif
